﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace Ukladanka
{
    class NPuzzles
    {
        private Puzzle[] _TablicaKlockow;
        private Bitmap _OstatniPuzzle;
        private Bitmap _calyObrazek;
        private int _WysokoscPuzzla;    //wysokosc i szerokosc kazdego puzzla w calej ukladance jest jednakowa
        private int _SzerokoscPuzzla;
        private int _PoziomTrudnosci;

        public NPuzzles(int rozmiar, Bitmap caly)
        {
            this._TablicaKlockow = new Puzzle[rozmiar*rozmiar];
            this._OstatniPuzzle = null;
            this._calyObrazek = caly;
            this._SzerokoscPuzzla = caly.Width / rozmiar;
            this._WysokoscPuzzla = caly.Height / rozmiar;
            this._PoziomTrudnosci = 4;
        }

        public void DodajPuzzle(Puzzle p, int i)
        {
            this._TablicaKlockow[i] = p;
        }

        public Bitmap WyswietlPuzzle(int nr)
        {
            return _TablicaKlockow[nr].WyswietlKlocek();
        }

        public void WymieszajUkladanke()
        {
            Random rand = new Random();

            for (int i = 1; i < this._TablicaKlockow.Length-1; i++)
            {
                int nr = rand.Next(i + 1);
                swap(i, nr);
            }
            this.UkryjOstatniKlocek();
        }

        //swap dwoch puzli polega na zamianie wspolrzednych x,y punku gornego lewego konta miedzy nimi
        private void swap(int n, int k)
        {
            Puzzle temp = this._TablicaKlockow[n];

            this._TablicaKlockow[n] = this._TablicaKlockow[k];
            this._TablicaKlockow[k] = temp;

        }

        public Image GenerujObrazUkladanki()
        {
            Bitmap currUkladanka = new Bitmap(this._calyObrazek.Width, this._calyObrazek.Height);
            Graphics g = Graphics.FromImage(currUkladanka);

            for (int i = 0; i < this._PoziomTrudnosci; i++)
            {
                for (int j = 0; j < this._PoziomTrudnosci; j++)
                {
                    g.DrawImage((Image)this._TablicaKlockow[i*this._PoziomTrudnosci+j].GetPuzzle(),
                        (j%this._PoziomTrudnosci)*this._SzerokoscPuzzla,
                        (i%this._PoziomTrudnosci)*this._WysokoscPuzzla,
                        this._SzerokoscPuzzla,
                        this._WysokoscPuzzla);
                }
            }
            return (Image)currUkladanka;
        }

        private void UkryjOstatniKlocek()
        {
            Rectangle rc = new Rectangle(0, 0, this._SzerokoscPuzzla, this._WysokoscPuzzla);
            Bitmap bit = new Bitmap(this._SzerokoscPuzzla, this._WysokoscPuzzla);
            Graphics g = Graphics.FromImage((Image)bit);
            SolidBrush sb = new SolidBrush(Color.AntiqueWhite);
            g.FillRectangle(sb, rc);

            this._OstatniPuzzle = this._TablicaKlockow[this._TablicaKlockow.Length-1].GetPuzzle();
            this._TablicaKlockow[this._TablicaKlockow.Length - 1].SetPuzzle(bit);
            this._TablicaKlockow[this._TablicaKlockow.Length - 1].SetNumerKlocka(-1);
        }

        public int GetSzerokoscPuzzla()
        {
            return this._SzerokoscPuzzla;
        }

        public int GetWysokoscPuzzla()
        {
            return this._WysokoscPuzzla;
        }

        public int GetPoziomTrudnosci()
        {
            return this._PoziomTrudnosci;
        }

        public void WykonajRuch(int nr)
        {
            int lewysasiad = nr % this._PoziomTrudnosci - 1;
            int prawysasiad = (nr + 1) % this._PoziomTrudnosci;
            int gornysasiad = nr - this._PoziomTrudnosci;
            int dolnysasiad = nr + this._PoziomTrudnosci;

            if (lewysasiad >= 0 && this._TablicaKlockow[nr - 1].GetNumerKlocka() == -1) 
            {
                swap(nr, nr - 1);
                return;
            }
            if (prawysasiad > 0 && this._TablicaKlockow[nr + 1].GetNumerKlocka() == -1)
            {
                swap(nr, nr + 1);
                return;
            }
            if (gornysasiad >= 0 && this._TablicaKlockow[gornysasiad].GetNumerKlocka() == -1)
            {
                swap(nr, gornysasiad);
                return;
            }
            if (dolnysasiad < this._TablicaKlockow.Length && this._TablicaKlockow[dolnysasiad].GetNumerKlocka() == -1)
            {
                swap(nr, dolnysasiad);
                return;
            }
        }
    }
}
